import os
import sys
import uuid
import shutil
import cocos
import cocos_project
from string import upper

class CCPluginSdk(cocos.CCPlugin):
    
    DE_LANGUAGE = ('cpp', 'lua')
    
    DE_TP_ANDROID = {
        'cpp':'/proj.android',
        'lua':'/proj.android'
    }
    
    DE_RES_ANDROID = {
        'lib_static':'\nLOCAL_WHOLE_STATIC_LIBRARIES += cocos_sdk_static',
        'lib_include':'\n$(call import-module,external/libsdk)'
    }
    
    DE_KEY_ANDROID = {
        'lib_static':'LOCAL_WHOLE_STATIC_LIBRARIES',
        'lib_include':'$(call import-module'
    }
    
    DE_TP_WIN32 = {
        'cpp':'/proj.win32',
        'lua':'/proj.win32'
    }
    
    DE_RES_WIN32 = {
        'sln_proj':'Project("{%s}") = "libsdk", "..\..\..\external\libsdk\proj.win32\libsdk.vcxproj", "{%s}"\nEndProject\n',
        'sln_proj_build':'\n\t\t{%s}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{%s}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{%s}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{%s}.Release|Win32.Build.0 = Release|Win32',
        'vcx_proj':'<ProjectReference Include="..\..\..\external\libsdk\proj.win32\libsdk.vcxproj">\n\t\t\t<Project>{%s}</Project>\n\t\t\t<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n\t\t</ProjectReference>',
        'vcx_proj_head':'$(ProjectDir)..\..\..\external\libsdk;'
    }
    
    DE_KEY_WIN32 = {
        'sln_proj':'EndProject\n',
        'sln_proj_build':'postSolution',
        'vcx_proj':'</ProjectReference>',
        'vcx_proj_head':'<AdditionalIncludeDirectories>'
    }
    
    DE_TP_IOS = {
        'cpp':'/proj.ios',
        'lua':'/proj.ios'
    }
    
    DE_RES_IOS = {
        'build_file':'\n\t\t%s /* CCSdk.mm in Sources */ = {isa = PBXBuildFile; fileRef = %s /* CCSdk.mm */; };',
        'ref_file':'\n\t\t%s /* CCSdk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCSdk.h; path = ../../../external/libsdk/CCSdk.h; sourceTree = "<group>"; };\n\t\t%s /* CCSdk.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CCSdk.mm; path = ../../../external/libsdk/proj.ios/CCSdk.mm; sourceTree = "<group>"; };\n\t\t%s /* OCSdk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OCSdk.h; path = ../../../external/libsdk/proj.ios/OCSdk.h; sourceTree = "<group>"; };',
        'group':'\n\t\t%s /* libsdk */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t%s /* OCSdk.h */,\n\t\t\t\t%s /* CCSdk.mm */,\n\t\t\t\t%s /* CCSdk.h */,\n\t\t\t);\n\t\t\tname = libsdk;\n\t\t\tsourceTree = "<group>";\n\t\t};',
        'group_ref':'\t\t\t\t%s /* libsdk */,\n',
        'sou_build':'\n\t\t\t\t%s /* CCSdk.mm in Sources */,',
        'head_scan':'\n\t\t\t\t\t"\\"$(SRCROOT)/../../../external/libsdk\\"",\n\t\t\t\t\t"\\"$(SRCROOT)/../../../external/libsdk/proj.ios\\"",'
    }
    
    DE_KEY_IOS = {
        'build_file':'/* Begin PBXBuildFile section */',
        'ref_file':'/* Begin PBXFileReference section */',
        'group':'/* Begin PBXGroup section */',
        'group_ref':'CustomTemplate */ = {',
        'sou_build':'/* Begin PBXSourcesBuildPhase section */',
        'head_scan':'HEADER_SEARCH_PATHS = ('
    }

    @staticmethod
    def plugin_name():
        return 'sdk'

    @staticmethod
    def brief_description():
        return "project sdk lib"
    
    def run(self, argv, dependencies):
        if len(argv) == 0 or argv[0] == '--help':
            utils.plugin_help()
        else:
            platform = argv[argv.index('-p') + 1] if '-p' in argv and len(argv) >= 2 else None
            language = argv[argv.index('-l') + 1] if '-l' in argv and len(argv) >= (2 if platform == None else 4) else 'cpp'
            list_platform = {'android':utils.tp_android, 'ios':utils.tp_ios, 'win32':utils.tp_win32}
            
            # check language 
            if not language in CCPluginSdk.DE_LANGUAGE:
                print 'this is language fiald!'
                return
    
            if platform in list_platform.keys():
                list_platform[platform](language)
            else:
                for tp_platform in list_platform.values():
                    tp_platform(language)
    
    
class utils:
    
    @staticmethod
    def plugin_help():
        print 'cocos sdk [-p (android,ios,win32)] [-l (cpp)]'
    
    @staticmethod
    def get_project_path(path):
        return os.path.abspath(os.getcwd() + path)
    
    @staticmethod
    def get_libsdk_path(path):
        return os.path.abspath(os.path.dirname(__file__) + '/libsdk' + path)
    
    @staticmethod
    def get_project_name():
        str_proj = utils.get_project_path('/')
        return str_proj[len(os.path.dirname(str_proj)) + 1:]
    
    @staticmethod
    def read_file(path):
        cnt = None
        if os.path.exists(path):
            file = open(path)
            cnt = file.read()
            file.close()
        return cnt
    
    @staticmethod
    def write_file(path, cnt):
        file = open(path, 'wb')
        file.write(cnt)
        file.close()
    
    @staticmethod
    def edit_file(cnt, str_find, num, str_cnt, right_pos):
        if cnt != None:
            pos = 0
            for i in range(num):
                pos = cnt[pos:].find(str_find) + len(str_find) + pos
            pos = pos + right_pos
            cnt = cnt[:pos] + str_cnt + cnt[pos:]
        return cnt
        
    
    @staticmethod
    def tp_android(language):
        # copy JSdk.java
        path_src = utils.get_libsdk_path('/platform/android/JSdk.java')
        path_dst = utils.get_project_path(CCPluginSdk.DE_TP_ANDROID[language] + '/src/org/cocos2dx/sdk/JSdk.java')
        if not os.path.exists(path_dst):
            if not os.path.exists(os.path.dirname(path_dst)):
                os.makedirs(os.path.dirname(path_dst))
            shutil.copy(path_src, path_dst)
        
        # modify Android.mk file
        path_mk = utils.get_project_path(CCPluginSdk.DE_TP_ANDROID[language] + '/jni/Android.mk')
        cnt_mk = utils.read_file(path_mk)
        # check is install
        if cnt_mk.find('libsdk') == -1:
            cnt_mk = utils.edit_file(cnt_mk, CCPluginSdk.DE_KEY_ANDROID['lib_static'], 5, CCPluginSdk.DE_RES_ANDROID['lib_static'], 26)
            cnt_mk = utils.edit_file(cnt_mk, CCPluginSdk.DE_KEY_ANDROID['lib_include'], 4, CCPluginSdk.DE_RES_ANDROID['lib_include'], 11)
            utils.write_file(path_mk, cnt_mk)
        
    
    @staticmethod
    def tp_ios(language):
        str_proj = utils.get_project_name()
        
        # edit project.xcodeproj
        path_xcode = utils.get_project_path('/%s/%s.xcodeproj/project.pbxproj' % (CCPluginSdk.DE_TP_IOS[language], str_proj))
        cnt_xcode = utils.read_file(path_xcode)
        if cnt_xcode.find('libsdk') == -1:
            uid = uuid.uuid4()
            uuid_libsdk = utils._ios_get_uuid(uid, 0)
            uuid_ccsdk_h = utils._ios_get_uuid(uid, 1)
            uuid_ccsdk_mm = utils._ios_get_uuid(uid, 2)
            uuid_ocsdk_h = utils._ios_get_uuid(uid, 3)
            uuid_ccsdk_mm_build = utils._ios_get_uuid(uid, 4)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['build_file'], 1, CCPluginSdk.DE_RES_IOS['build_file'] % (uuid_ccsdk_mm_build, uuid_ccsdk_mm), 0)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['ref_file'], 1, CCPluginSdk.DE_RES_IOS['ref_file'] % (uuid_ccsdk_h, uuid_ccsdk_mm, uuid_ocsdk_h), 0)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['group'], 1, CCPluginSdk.DE_RES_IOS['group'] % (uuid_libsdk, uuid_ocsdk_h, uuid_ccsdk_mm, uuid_ccsdk_h), 0)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['group_ref'], 1, CCPluginSdk.DE_RES_IOS['group_ref'] % uuid_libsdk, 36)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['sou_build'], 1, CCPluginSdk.DE_RES_IOS['sou_build'] % uuid_ccsdk_mm_build, 120)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['head_scan'], 1, CCPluginSdk.DE_RES_IOS['head_scan'], 0)
            cnt_xcode = utils.edit_file(cnt_xcode, CCPluginSdk.DE_KEY_IOS['head_scan'], 2, CCPluginSdk.DE_RES_IOS['head_scan'], 0)
            utils.write_file(path_xcode, cnt_xcode)
        
    
    @staticmethod
    def _ios_get_uuid(uid, num):
        return '%8X%4X%12X' % (uid.fields[0] + num, uid.fields[1], uid.fields[5])
    
    @staticmethod
    def tp_win32(language):
        str_proj = utils.get_project_name()
        
        # edit projec.sln
        path_sln = utils.get_project_path('%s/%s.sln' % (CCPluginSdk.DE_TP_WIN32[language], str_proj))
        uuid_porj = utils._win32_get_sln_proj_uuid(path_sln)
        uuid_libsdk = upper(str(uuid.uuid4()))
        cnt_sln = utils.read_file(path_sln)
        if cnt_sln.find('libsdk') == -1:
            cnt_sln = utils.edit_file(cnt_sln, CCPluginSdk.DE_KEY_WIN32['sln_proj'], 6, CCPluginSdk.DE_RES_WIN32['sln_proj'] % (uuid_porj, uuid_libsdk), 0)
            cnt_sln = utils.edit_file(cnt_sln, CCPluginSdk.DE_KEY_WIN32['sln_proj_build'], 1, CCPluginSdk.DE_RES_WIN32['sln_proj_build'] % (uuid_libsdk, uuid_libsdk, uuid_libsdk, uuid_libsdk), 0)
            utils.write_file(path_sln, cnt_sln)
        # edit project.vcxproj
        path_vcx = utils.get_project_path('%s/%s.vcxproj' % (CCPluginSdk.DE_TP_WIN32[language], str_proj))
        cnt_vcx = utils.read_file(path_vcx)
        if cnt_vcx.find('libsdk') == -1:
            cnt_vcx = utils.edit_file(cnt_vcx, CCPluginSdk.DE_KEY_WIN32['vcx_proj'], 5, CCPluginSdk.DE_RES_WIN32['vcx_proj'] % uuid_libsdk, 0)
            cnt_vcx = utils.edit_file(cnt_vcx, CCPluginSdk.DE_KEY_WIN32['vcx_proj_head'], 1, CCPluginSdk.DE_RES_WIN32['vcx_proj_head'], 0)
            cnt_vcx = utils.edit_file(cnt_vcx, CCPluginSdk.DE_KEY_WIN32['vcx_proj_head'], 2, CCPluginSdk.DE_RES_WIN32['vcx_proj_head'], 0)
            utils.write_file(path_vcx, cnt_vcx)
        
        
    @staticmethod
    def _win32_get_sln_proj_uuid(path):
        cnt = utils.read_file(path)
        pos = cnt.find('Project("{') + len('Project("{')
        return cnt[pos:pos + 36]
